#include <cstdio>
#include <WinSock2.h>

#pragma comment(lib,"Ws2_32.lib")

#define SAFECALL( INVOCATION )	\
	{							\
		int ret = INVOCATION;	\
		if ( ret != 0 )			\
		{						\
			printf("failed to call #INVOCATION: %d\n", ret); \
			exit(ret);			\
		}						\
	}							\



void ActAsServer()
{
	printf("ActAs Server...\n");

	WSADATA wsadata;
	SAFECALL(WSAStartup(MAKEWORD(2,2), &wsadata));

	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s==INVALID_SOCKET)
	{
		printf("create socket failed: %d", s);
	}

	sockaddr_in service;
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = inet_addr("127.0.0.1");
	service.sin_port = htons(5678);

	if (bind( s, (sockaddr *)&service, sizeof(service)) != SOCKET_ERROR) 
	{
		if (listen( s, 10 ) != SOCKET_ERROR)
		{
			SOCKET as;
			while(1)
			{
				as = accept(s, 0, 0);
				if (as != INVALID_SOCKET )
				{
					char buf[1024]="Hello!";
					int len = recv(as, buf, (int)sizeof(buf), 0);
					buf[len] = 0;
					printf("Got %s\n", buf);
					send(as, buf, strlen(buf), 0);
				}
			}
		}
	}
	else
	{
		printf("failed to bind %ld", WSAGetLastError());
	}

	SAFECALL(closesocket(s));
	WSACleanup();
}

void ActAsClient(int argc, char *argv[])
{
	printf("ActAs Client...\n");

	WSADATA wsadata;
	SAFECALL(WSAStartup(MAKEWORD(2,2), &wsadata));

	SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (s==INVALID_SOCKET)
	{
		printf("create socket failed: %d", s);
	}

	sockaddr_in service;
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = inet_addr("127.0.0.1");
	service.sin_port = htons(5678);

	if (connect( s, (sockaddr *)&service, sizeof(service)) != SOCKET_ERROR) 
	{
		char * msg = (argc==3) ? argv[2] : "Hello!";
		if (send(s, msg, strlen(msg), 0) <= 0 )
		{
			printf("failed to send: %ld", WSAGetLastError());
			
		}
		char buf[1024];
		int len = recv(s, buf, sizeof(buf), 0);
		buf[len] = 0;
		printf("Recieved: %s\n", buf);
	}
	else
	{
	}

	SAFECALL(closesocket(s));
	WSACleanup();
}

int main(int argc, char *argv[])
{
	if (argc >= 2)
	{
		if (strcmp(argv[1], "server")==0)
		{
			ActAsServer();
		}
		else if (strcmp(argv[1], "client")==0)
		{
			ActAsClient(argc, argv);
		}
	}
	return 0;
}